'''
Description: 文件发送器模块
Author: HowsenFisher
Date: 2021-04-07 22:29:35
LastEditTime: 2021-04-11 01:08:14
LastEditors: liutq
Reference: 
'''
import socket
import time
import sys
import os
class FileSender:
    '''
    @description: 文件发送器类
    @param  {*}
    @return {*}
    @param {*} self
    @param {*} parent：父对象
    @param {*} ip：目标IP
    @param {*} port：文件传输端口
    @param {*} filepath：想要发送的文件路径
    @param {*} id：Debug用
    '''
    def __init__(self,parent,ip,port,filepath,id):
        # 父对象
        self.parent = parent
        # 打印info
        self.parent.newInfoSignal.emit("文件发送器初始化:%s"%id)
        ##建立TCP socket
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 打印info
        self.parent.newInfoSignal.emit("文件发送器尝试连接 %s:%s"%(ip,port))
        self.s.settimeout(2)
        # 不断尝试连接目标，直到成功,2s超时return
        while True:
            try:
                self.s.connect((ip,port))
                break
            except Exception:
                return
        # 打印info
        self.parent.newInfoSignal.emit("文件发送器初始化:%s"%id)
        # 文件路径
        self.filepath = filepath
        # 文件发送，发送长度10240
        self.send(10240)
    
    def send(self,length):
        # 打开文件，获取bytes
        myfile = open(self.filepath,"rb")
        fileBytes = myfile.read()
        
        start = 0
        # 获取文件名
        filename = "/".join(self.filepath.split("/")[2:])
        # 向对方发送文件名称
        self.s.send(filename.encode("utf-8"))
        # 监测对方的filename返回值
        while True:
            # 接收数据
            data = self.s.recv(10240)
            # 若收到"filename ok"，说明文件名发送成功
            if data==b"filename ok":
                print("filename send ok")
                break
        # 开始文件发送，记录时间
        starttime = time.time()
        count=0
        while True:
            count+=1
            # 截取一段长度的文件（文件分段）
            sendBytes = fileBytes[start:start+length]
            # 截取成功（非空）
            if sendBytes:
                # 发送数据
                self.s.send(sendBytes)

                if count%100==0:
                    speed = 0
                    # 尝试计算发送速率，每发送100次统计一次
                    try:
                        # 现在的时间
                        currenttime = time.time()
                        # 已经过去的时间
                        dertaTime = (currenttime-starttime)
                        # 速度=100次发送的长度/时间差
                        speed = length*100/dertaTime/1024
                        # self.speedShow['text']="传输速度:%fKB/s"%speed
                        # 打印info
                        self.parent.newInfoSignal.emit("传输速度:%fKB/s"%speed)
                        starttime = time.time()
                    # 如果发生时间间隔太短导致除法溢出，就抛弃此次速度计算
                    except Exception:
                        pass
                start += length
                # 计算进度
                jindu = start/len(fileBytes)*100
                # self.progressbar['value']=jindu
                # print(jindu)
            else:
                break
            # 等待接收方的接收完毕反馈
            while True:
                # 接收数据
                data = self.s.recv(length)
                # 如果是接收完毕反馈则跳出循环
                if data == b'receive ok':
                    break
        # 向对方发送文件发送完毕消息
        self.s.send("file send finish!".encode("utf-8"))
        # 打印info
        self.parent.newInfoSignal.emit("文件%s发送成功!"%self.filepath)
    
if __name__ == "__main__":
    myFileSender = FileSender("./1.docx",("127.0.0.1",913))
    myFileSender.send(10240)
        

